﻿using System;
using System.Collections.Generic;
using System.Text;

namespace FySystem.Net.SimSocket.Protocals
{
    internal abstract class HandlerBase
    {
        internal enum EPackTypes
        {
            /// <summary>
            /// 普通信息包
            /// </summary>
            Normal=0,
            /// <summary>
            /// 心跳，ping
            /// </summary>
            Ping=1,
            /// <summary>
            /// 心跳，pong
            /// </summary>
            Pong=2,
            /// <summary>
            /// 关闭
            /// </summary>
            Close=3,
            /// <summary>
            /// 预留
            /// </summary>
            Reserved=4
        };

        #region 通用函数
        /// <summary>
        /// 校验握手信息
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="bytesRead"></param>
        /// <param name="helloInfo"></param>
        /// <param name="handlerBase"></param>
        /// <returns></returns>
        internal static bool ValidateHello(ref byte[] buffer, int bytesRead, ref HelloInfo helloInfo, ref HandlerBase handlerBase)
        {
            bool res = false;
            try
            {
                if (bytesRead <= 0)
                    return false;

                helloInfo = helloInfo == null ? new HelloInfo() : helloInfo;
                helloInfo.Version = buffer[bytesRead - 1];

                handlerBase = HandlerManager.GetHandlerByVersion(helloInfo.Version);
                if (handlerBase == null)
                    return res;

                res = handlerBase.ValidateHello(ref buffer, bytesRead, ref helloInfo);
            }
            catch (Exception)
            {
                throw;
            }
            return res;
        }

        /// <summary>
        /// 将GUID字节数组转换为字符串
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        internal static string ConvertGUID(byte[] bytes)
        {
            StringBuilder res = new StringBuilder(32);
            try
            {
                for (int i = 0; i < bytes.Length; i++)
                    res.Append(bytes[i].ToString("X2"));
            }
            catch (Exception)
            {
                throw;
            }
            return res.ToString();
        }
        #endregion

        #region 函数声明，派生类中实现
        /// <summary>
        /// 创建客户端->服务端的握手包
        /// </summary>
        /// <returns></returns>
        internal abstract byte[] GenHelloCSPackage(byte[] byteGuid, ushort version);
        /// <summary>
        /// 校验握手信息
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="bytesRead"></param>
        /// <param name="helloInfo"></param>
        /// <returns></returns>
        internal abstract bool ValidateHello(ref byte[] buffer, int bytesRead, ref HelloInfo helloInfo);
        /// <summary>
        /// 创建服务端->客户端的握手回应包
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        internal abstract byte[] GenHelloSCPackage(ref byte[] buffer, bool valResult);
        /// <summary>
        /// 校验握手回复
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="bytesRead"></param>
        /// <returns></returns>
        internal abstract bool ValidateHelloReply(ref byte[] buffer, int bytesRead);
        /// <summary>
        /// 解析数据包
        /// </summary>
        /// <param name="stateObjectBase"></param>
        /// <param name="bytesRead"></param>
        /// <returns></returns>
        internal abstract List<FrameInfo> DepackFrame(SimStateObjectBase stateObjectBase, int bytesRead);
        /// <summary>
        /// 生成ping数据包
        /// </summary>
        /// <returns></returns>
        internal abstract byte[] GenPingPackage();
        /// <summary>
        /// 生成pong数据包
        /// </summary>
        /// <returns></returns>
        internal abstract byte[] GenPongPackage();
        /// <summary>
        /// 打包
        /// </summary>
        /// <param name="packInfo"></param>
        /// <returns></returns>
        internal abstract byte[] PackFrame(PackInfo packInfo);
        /// <summary>
        /// 以默认OpCode为0，IsFinish为true打包
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        internal abstract byte[] PackFrame(ref byte[] data);
        /// <summary>
        /// 以默认OpCode为0，IsFinish为true打包
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        internal abstract byte[] PackFrame(List<byte> data);
        #endregion

    }
}
